{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# hvPlot.heatmap\n",
    "\n",
    "```{eval-rst}\n",
    ".. currentmodule:: hvplot\n",
    "\n",
    ".. automethod:: hvPlot.heatmap\n",
    "```\n",
    "\n",
    "## Backend-specific styling options\n",
    "\n",
    "```{eval-rst}\n",
    ".. backend-styling-options:: heatmap\n",
    "```\n",
    "\n",
    "## Examples\n",
    "\n",
    "Heatmaps are ideal for visualizing values across two dimensions as a color-coded matrix. They are commonly used for temporal data, correlation grids, and density summaries."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic heatmap plot with aggregation\n",
    "\n",
    "The `heatmap` plot can aggregate the data when provided in long form."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas  # noqa\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame({\n",
    "    \"cat1\": [\"A\", \"A\", \"A\", \"B\", \"B\", \"B\"],\n",
    "    \"cat2\": [\"X\", \"X\", \"Y\", \"Y\", \"Y\", \"Y\"],\n",
    "    \"values\": [1, 2, 3, 4, 5, 6],\n",
    "})\n",
    "\n",
    "df.hvplot.heatmap(x=\"cat1\", y=\"cat2\", C=\"values\", reduce_function=np.mean)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic heatmap plot without aggregation\n",
    "\n",
    "No aggregation is required when the data is provided in wide format. The color/tooltip of a cell is derived from its corresponding value in the dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas  # noqa\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(\n",
    "    {\"2020\": [10, 35], \"2021\": [40, 30], \"2022\": [20, 25]},\n",
    "    index=[\"A\", \"B\"],\n",
    ")\n",
    "\n",
    "df.hvplot.heatmap()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Heatmap of earthquake counts by depth and magnitude\n",
    "\n",
    "Let's use a more realistic dataset. This plot visualizes the count of earthquakes categorized by both depth and magnitude class. It gives a clear overview of how often each type of earthquake occurs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas # noqa\n",
    "import numpy as np\n",
    "\n",
    "df = hvplot.sampledata.earthquakes('pandas')\n",
    "\n",
    "df.hvplot.heatmap(\n",
    "    x='mag_class',\n",
    "    y='depth_class',\n",
    "    C='mag',\n",
    "    reduce_function=np.size,\n",
    "    fields={'mag': 'count'},  # for the tooltip to display count instead of mag \n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Use of `reduce_function`\n",
    "\n",
    "`reduce_function` specifies the function used to aggregate the values of `C` for each combination of `x` and `y` after grouping. Numpy functions are appropriate, like in the example below with `np.nanmedian`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas  # noqa\n",
    "\n",
    "df = hvplot.sampledata.penguins('pandas')\n",
    "\n",
    "df.hvplot.heatmap(\n",
    "    x='species', y='island', C='body_mass_g',\n",
    "    reduce_function=np.nanmedian, clabel='Median body mass (g)',\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Use of `logz`\n",
    "\n",
    "This version applies a logarithmic color scale to better distinguish lower-frequency combinations, which may be overshadowed by dominant bins in a linear scale."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas # noqa\n",
    "import numpy as np\n",
    "\n",
    "df = hvplot.sampledata.earthquakes('pandas')\n",
    "\n",
    "df.hvplot.heatmap(\n",
    "    x='mag_class', y='depth_class', C='mag', logz=True,\n",
    "    reduce_function=np.size, fields={'mag': 'count'}\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### More information when no aggregation\n",
    "\n",
    "`x` and `y` can be set differently in this case."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hvplot.pandas  # noqa\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(\n",
    "    {\"2020\": [10, 35], \"2021\": [40, 30], \"2022\": [20, 25]},\n",
    "    index=[\"A\", \"B\"],\n",
    ")\n",
    "df.index.name = \"Group\"\n",
    "\n",
    "plot_opts = dict(xaxis=\"top\", width=400, height=200, flip_yaxis=True)\n",
    "(\n",
    "    df.hvplot.heatmap(**plot_opts, title=\"From array, without setting x and y\") +\n",
    "    df.hvplot.heatmap(x=\"columns\", y=\"index\", title=\"From array, setting columns/index\", **plot_opts) +\n",
    "    df.hvplot.heatmap(x=\"columns\", y=\"Group\", title=\"From array, setting columns/index name\", **plot_opts)\n",
    ").cols(1)"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
